{% extends "api.html" %}
{% block api_content %}
<p style="font-size: 14px;"><em>Jump to: </em> <a href="#boss_web_test"><code>boss_web_test</code></a>
&nbsp; <a href="#boss_assert">boss_assert</a></p>
<p>Chicago Boss ships with a unique functional test framework, where tests are structured as trees of continuations. All assertions are performed in callbacks, and additional tests are also performed in callbacks. For more information on the design of Boss's functional tests, see <a href="http://www.evanmiller.org/functional-tests-as-a-tree-of-continuations.html">&#8220;Functional Tests As A Tree Of Continuations&#8221;</a>.</p>

<p>To create a test suite, create a module in the <code>src/test/functional/</code> directory. Your test module should export a <code>start/0</code> function, which should invoke a function from the <code>boss_web_test</code> module. This function will in turn invoke functions in the <a href="#boss_assert"><code>boss_assert</code></a> module (to run assertions) and the <a href="#boss_web_test"><code>boss_web_test</code></a> module (to run further tests). A simple example of a test module with included <code>start/0</code> function would be:</p>

<pre class="code">
<span class="attr">-module</span>(my_app_test).

<span class="attr">-export</span>([start/0]).

start() -&gt;
    boss_web_test:get_request("/", [],
        [fun boss_assert:http_ok/1], []).
</pre>

<p>The above test issues a GET request to the root URL, asserts that the response is 200 OK, and quits.</p>

<p>When you are ready to run your test suite, type "./rebar boss c=test_functional" in your project directory.</p>

<a name="boss_web_test"></a>
<h2>boss_web_test</h2>
<p>Functions in the <code>boss_web_test</code> issue HTTP requests to your web application (or check for emails sent by it). All functions in the <code>boss_web_test</code> module take the same two final arguments.</p>

<p>Second to last, <code>Assertions</code> is a list of funs that must return a tuple <code>{Passed, ErrorMessage}</code>, where:
<ul>
    <li><code>Passed</code> - a boolean indicating whether the test passed</li>
    <li><code>ErrorMessage</code> - an error message to be displayed if the test failed</li>
</ul>
<p>Each fun in <code>Assertions</code> takes a single argument, which is the response object of the current test. The response object will usually by an HTTP response, but in <code>boss_web_test:read_email/4</code>, it's an email.</p>

<p>Most assertions will take the form of calls to <a href="#boss_assert"><code>boss_assert</code></a>, which is documented below.</p>

<p>The last argument to any <code>boss_web_test</code> function is called <code>Continuations</code>. <code>Continuations</code> is a list of additional tests &mdash; funs that take the HTTP response value as their only argument, and use it to invoke additional tests from the <code>boss_web_test</code> module. Funs in <code>Continuations</code> should be preceded by a string label, e.g.:</p>

<pre class="code">
boss_web_test:get_request("/", [], [],
   [ "Click the register link", fun(Res) -&gt; ... end,
     "Click the copyright link", fun(Res) -&gt; ... end,
      ... ]).
</pre>
<p>The key thing to understand about <code>Continuations</code> is that they are <em>performed in parallel</em>. Any database manipulations that occur in one continuation cannot affect sibling continuations.</p>

<p>Functions available in the <code>boss_web_test</code> module include:</p>

{% for function in test_functions %}
    {% if function.description_long %}
        <div class="example {% cycle 'row1' 'row2' %}">
          <div class="code spec">
                {{ function.function }}{% if function.typespec %}{{ function.typespec }}{% endif %}
            </div>
            <p>{{ function.description_long }}</p>
        </div>
    {% endif %}
{% endfor %}

<a name="boss_assert"></a>
<h2>boss_assert</h2>

<p>The <code>Assertions</code> list in a <code>boss_web_test</code> invocation will usually refer to functions in the <code>boss_assert</code> module. Available functions include:</p>

{% for function in assert_functions %}
    {% if function.description_long %}
        <div class="example {% cycle 'row1' 'row2' %}">
          <div class="code spec">
                {{ function.function }}{% if function.typespec %}{{ function.typespec }}{% endif %}
            </div>
            <p>{{ function.description_long }}</p>
        </div>
    {% endif %}
{% endfor %}

{% endblock %}
